package cn.hengzhu.main_manager.utils.task;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.hengzhu.main_manager.repository.dao.AccessRecordMapper;
import cn.hengzhu.main_manager.repository.dao.CustomersAmountMapper;
import cn.hengzhu.main_manager.repository.dao.ManageCaseBoxMapper;
import cn.hengzhu.main_manager.repository.dao.ManageCaseMapper;
import cn.hengzhu.main_manager.repository.dao.ManageCaseTypeMapper;
import cn.hengzhu.main_manager.repository.dao.PrepayOrderMapper;
import cn.hengzhu.main_manager.repository.dao.SysConstMapper;
import cn.hengzhu.main_manager.repository.domain.AccessRecord;
import cn.hengzhu.main_manager.repository.domain.CustomersAmount;
import cn.hengzhu.main_manager.repository.domain.ManageCase;
import cn.hengzhu.main_manager.repository.domain.ManageCaseBox;
import cn.hengzhu.main_manager.repository.domain.ManageCaseBoxExample;
import cn.hengzhu.main_manager.repository.domain.ManageCaseExample;
import cn.hengzhu.main_manager.repository.domain.ManageCaseType;
import cn.hengzhu.main_manager.repository.domain.ManageCaseTypeExample;
import cn.hengzhu.main_manager.repository.domain.PrepayOrder;
import cn.hengzhu.main_manager.repository.domain.PrepayOrderExample;
import cn.hengzhu.main_manager.repository.domain.SysConst;
import cn.hengzhu.main_manager.repository.domain.SysConstExample;
import cn.hengzhu.main_manager.repository.vo.CaseInitVO;
import cn.hengzhu.main_manager.service.ManageCaseService;
import cn.hengzhu.main_manager.service.PayOrderService;
import cn.hengzhu.main_manager.service.SysConstService;
import cn.hengzhu.main_manager.utils.CustomersAmountCount;
import cn.hengzhu.main_manager.utils.DateTimeHelper;
import cn.hengzhu.main_manager.utils.DetailDate;
import cn.hengzhu.main_manager.utils.HttpClientUtil;
import cn.hengzhu.main_manager.utils.MessageData;
import cn.hengzhu.main_manager.utils.MessageTemplate;
import cn.hengzhu.main_manager.utils.SavaSourceToRecordSource;
import cn.hengzhu.main_manager.utils.config.AllConst;
import cn.hengzhu.main_manager.utils.config.AppConfig;
import cn.hengzhu.main_manager.utils.config.gzh.WeiXinConst;

/**
 * mq消费者
 */
@Component(value = "quartzJob")
public class QuertzTask implements MessageListener {
	@Autowired
	private ManageCaseBoxMapper manageCaseBoxMapper;
	@Autowired
	private ManageCaseMapper manageCaseMapper;
	@Autowired
	private SysConstMapper sysConstMapper;
	@Autowired
	private ManageCaseService manageCaseService;
	@Autowired
	private PrepayOrderMapper prepayOrderMapper;
	@Autowired
	private PayOrderService payOrderService;
	@Autowired
	private SysConstService sysConstService;
	@Autowired
	private AccessRecordMapper accessRecordMapper;
	@Autowired
	private ManageCaseTypeMapper manageCaseTypeMapper;
	@Autowired
	private CustomersAmountMapper customersAmountMapper;

	//如果链接redis失败则执行原来流程（切换定时获取message内容）
	public static boolean isConnRedisFlag = true;

	private static List<CaseInitVO> list = new ArrayList<>();

	@Override
	public void onMessage(Message message) {
		try {
			byte[] body = message.getBody();
			String msg = new String(body, "utf-8");
			System.out.println("QuertzTask 消费者接收到的消息： " + msg);
			ObjectMapper mapper = new ObjectMapper();
			CaseInitVO readValue = mapper.readValue(msg, CaseInitVO.class);
			if(isConnRedisFlag){
				manageCaseService.redisCacheValidata(readValue);
			}else {
				list.add(readValue);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 定时任务
	 */
	public void work(){
		if(isConnRedisFlag){
			manageCaseService.boxsInfoPutReids();
		}else{
			List<CaseInitVO> copyList = new ArrayList<>();
			copyList.addAll(list);
			list.clear();
			manageCaseService.doCaseWork(copyList);
		}
	}
	
	/*
	@Override
	public void onMessage(Message message) {
		try {
			byte[] body = message.getBody();
			String msg = new String(body, "utf-8");
			ObjectMapper mapper = new ObjectMapper();
			CaseInitVO readValue = mapper.readValue(msg, CaseInitVO.class);
			list.add(readValue);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}*/
	/*public void work() {
		List<CaseInitVO> copyList = new ArrayList<>();
		copyList.addAll(list);
		list.clear();
		manageCaseService.doCaseWork(copyList);
	}*/

	/**
	 * @author 刘成
	 * @since 2018年7月27日 更新token
	 */
	public void getTokenWork() {
		manageCaseService.getToken();
	}

	/**
	 * @author liuCheng
	 * @since 2018年12月10日 下午5:35:54
	 * @throws Exception
	 *             储物柜的到期时间发送的消息
	 */
	/*public void useTime() throws Exception {
		ManageCaseUsetimeExample manageCaseUsetimeExample = new ManageCaseUsetimeExample();
		List<ManageCaseUsetime> ManageCaseUsetimeList = manageCaseUsetimeMapper
				.selectByExample(manageCaseUsetimeExample);
		if (!ManageCaseUsetimeList.isEmpty()) {
			for (ManageCaseUsetime manageCaseUsetime : ManageCaseUsetimeList) {
				String caseNo = manageCaseUsetime.getCaseNo();
				long time = manageCaseUsetime.getUseEndTime().getTime();
				long now = new Date().getTime();
				if (now > time) {
					Connection connection = ConnectionUtils.getConnection();
					Channel channel = connection.createChannel();
					Map<String, Object> sendMap = new HashMap<>();
					sendMap.put("code", 0);
					ObjectMapper mapper = new ObjectMapper();
					Map<String, Object> args = new HashMap<String, Object>();
					args.put("x-message-ttl", 40000);
					channel.queueDeclare(caseNo, true, false, false, args);
					String writeValueAsString = mapper.writeValueAsString(sendMap);
					channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
					channel.close();
					connection.close();
				}
			}
		}
	}*/

	/**
	 * @author liuCheng
	 * @since 2018年12月10日 下午5:37:50 预支付订单过期处理
	 */
	public void prepayOrder() {

		Calendar calendar = Calendar.getInstance();
		SysConstExample sysConstExample = new SysConstExample();
		sysConstExample.createCriteria().andNameEqualTo(AppConfig.PAY_TIME_OUT);
		List<SysConst> selectByExample = sysConstMapper.selectByExample(sysConstExample);
		String value = selectByExample.get(0).getValue();
		Integer valueOf = Integer.valueOf("-" + value);
		calendar.add(Calendar.MINUTE, valueOf);
		Date time = calendar.getTime();
		PrepayOrderExample prepayOrderExample = new PrepayOrderExample();
		prepayOrderExample.createCriteria().andCreartTimeLessThan(time);
		List<PrepayOrder> prepayOrderList = prepayOrderMapper.selectByExample(prepayOrderExample);
		if (!prepayOrderList.isEmpty()) {
			List<Integer> prepayOrderIds = prepayOrderList.stream()
					.collect(Collectors.mapping(PrepayOrder::getId, Collectors.toList()));
			List<Integer> boxIds = prepayOrderList.stream()
					.collect(Collectors.mapping(PrepayOrder::getBoxId, Collectors.toList()));

			payOrderService.timeOutPrepayOrder(prepayOrderIds, boxIds);
		}

	}

	/**
	 * @author 刘成
	 * @throws ParseException
	 * @since 2018年7月27日 公众号发送超时提醒
	 */
	public void sendTemMessage() throws ParseException {
		// 八小时为默认超时时间
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 八小时前
		calendar.add(Calendar.HOUR_OF_DAY, -8);
		Date time = calendar.getTime();

		String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");

		Date parseToDate = DateTimeHelper.parseToDate(dateStr, "yyyy-MM-dd");

		List<ManageCaseBox> allUserList = manageCaseBoxMapper.getTimeOutUser(time, dateStr);
		if (!allUserList.isEmpty()) {
			// 每次发消息都会重新获取token以免发送失败
			manageCaseService.getToken();
			// 拿到所有的caseNO
			List<String> caseNoList = allUserList.stream()
					.collect(Collectors.mapping(ManageCaseBox::getCaseNo, Collectors.toList())).stream().distinct()
					.collect(Collectors.toList());
			// 拿到所有的open_id
			List<String> openidList = allUserList.stream()
					.collect(Collectors.mapping(ManageCaseBox::getUserId, Collectors.toList())).stream().distinct()
					.collect(Collectors.toList());
			// 拿到open_id对应的caseNO
			Map<String, ManageCaseBox> openIdMapBox = allUserList.stream()
					.collect(Collectors.toMap(ManageCaseBox::getUserId, a -> a));

			// 查询所有的case

			ManageCaseExample example = new ManageCaseExample();
			example.createCriteria().andCaseNoIn(caseNoList);
			List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(example);
			// case的map
			Map<String, ManageCase> caseMapByCaseNo = manageCaseList.stream()
					.collect(Collectors.toMap(ManageCase::getCaseNo, a -> a));

			openidList.stream().forEach(a -> {
				ManageCaseBox manageCaseBox = openIdMapBox.get(a);
				String caseNo = manageCaseBox.getCaseNo();
				ManageCase manageCase = caseMapByCaseNo.get(caseNo);

				MessageTemplate messageTemplate = new MessageTemplate();
				messageTemplate.setTouser(a);
				MessageData data = new MessageData();
				DetailDate first = new DetailDate();
				first.setValue("您好，您使用储物柜已超时");
				data.setFirst(first);
				DetailDate keyword1 = new DetailDate();
				keyword1.setValue(manageCase.getPlace());
				data.setKeyword1(keyword1);
				DetailDate keyword2 = new DetailDate();
				keyword2.setValue(manageCaseBox.getDoorNum() + "号门");
				data.setKeyword2(keyword2);
				DetailDate keyword3 = new DetailDate();
				keyword3.setValue(
						DateTimeHelper.formatDateTimetoString(manageCaseBox.getSaveTime(), "yyyy-MM-dd HH:mm:ss"));
				data.setKeyword3(keyword3);
				DetailDate remar = new DetailDate();
				remar.setValue("管理员会定期对超时的储物柜进行清理，请及时取走您的物品，感谢您的使用。");
				data.setRemark(remar);
				messageTemplate.setData(data);
				String jsonString = JSONObject.toJSONString(messageTemplate);

				SysConstExample example1 = new SysConstExample();
				example1.createCriteria().andNameEqualTo("ACCESS_TOKEN");
				List<SysConst> sysConst = sysConstMapper.selectByExample(example1);
				String accessToken = sysConst.get(0).getValue();
				String url = WeiXinConst.MESSAGE_TEMPLATE.replace("ACCESS_TOKEN", accessToken);
				String httpPost = HttpClientUtil.httpPost(url, jsonString);
				JSONObject parseObject = JSONObject.parseObject(httpPost);
				Object errcode = parseObject.get("errcode");
				if (errcode.equals(0)) {
					Integer id = manageCaseBox.getId();
					ManageCaseBox record = new ManageCaseBox();
					record.setId(id);
					record.setSendMessageDate(parseToDate);
					manageCaseBoxMapper.updateByPrimaryKeySelective(record);
				}
			});
		}
	}

	/**
	 * @author liuCheng
	 * @since 2018年12月24日 下午2:03:23 小程序发送超时提醒
	 */
	// public void sendTemMessageByWXXcx() {
	// List<ManageCaseBox> aliMessageList = new ArrayList<>();// 阿里
	// List<ManageCaseBox> wxMessageList = new ArrayList<>();// 微信
	// List<Integer> boxIdList = new ArrayList<>();// 已发消息的Id列表
	// // 查询储物柜到了发超时消息的柜子
	// Calendar calendar = Calendar.getInstance();
	// calendar.add(Calendar.HOUR_OF_DAY, 2);// 超时前两小时发送超时消息
	// Date time = calendar.getTime();
	// ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
	//
	// manageCaseBoxExample.createCriteria().andIsDelEqualTo((byte)
	// 0).andUseStatusEqualTo((byte)
	// 1).andClearBoxTimeLessThanOrEqualTo(time).andSendXcxMessageFlagEqualTo((byte)
	// 0);
	// List<ManageCaseBox> manageCaseBoxList =
	// manageCaseBoxMapper.selectByExample(manageCaseBoxExample);
	// if (!manageCaseBoxList.isEmpty()) {
	//
	// List<String> caseNoList =
	// manageCaseBoxList.stream().collect(Collectors.mapping(ManageCaseBox::getCaseNo,
	// Collectors.toList())).stream().distinct().collect(Collectors.toList());
	// ManageCaseExample manageCaseExample = new ManageCaseExample();
	// manageCaseExample.createCriteria().andCaseNoIn(caseNoList);
	// List<ManageCase> manageCaseList =
	// manageCaseMapper.selectByExample(manageCaseExample);
	// Map<String, ManageCase> manageCaseNoMap =
	// manageCaseList.stream().collect(Collectors.toMap(ManageCase::getCaseNo, v ->
	// v));
	//
	//
	// manageCaseBoxList.forEach(a -> {
	// Byte saveSource = a.getSaveSource();
	// if (saveSource.equals(AllConst.CASE_BOX_SAVE_SOURCE.ALI_XCX_SAVE_SOURCE)) {
	// aliMessageList.add(a);
	// } else if
	// (saveSource.equals(AllConst.CASE_BOX_SAVE_SOURCE.WX_XCX_SAVE_SOURCE)) {
	// wxMessageList.add(a);
	// }
	// });
	// if (!aliMessageList.isEmpty()) {//支付宝
	// aliMessageList.forEach(a->{
	// Date saveTime = a.getSaveTime();
	// String userId = a.getUserId();
	// String prepayId = a.getPrepayId();
	// try {
	// SendXcxMessageUtil.sendMessageToAli(prepayId, userId, saveTime);
	// } catch (Exception e) {
	//
	//
	//
	// }
	// });
	//
	// } else if (!wxMessageList.isEmpty()) {// 微信
	// SysConstExample sysExample = new SysConstExample();
	// sysExample.createCriteria().andNameEqualTo(WxConfig.ACCESS_TOKEN);
	// List<SysConst> sysConst = sysConstMapper.selectByExample(sysExample);
	// String access_token = sysConst.get(0).getValue();
	//
	// wxMessageList.forEach(a -> {
	// String prepayId = a.getPrepayId();
	// String caseNo = a.getCaseNo();
	// ManageCase manageCase = manageCaseNoMap.get(caseNo);
	// Integer boxId = a.getId();
	//
	// if(StringUtils.isNotBlank(prepayId)){
	// Integer code = SendXcxMessageUtil.sendWxMessage(a, manageCase, access_token,
	// time);
	// if (code.equals(40001) || code.equals(42001)) {
	// sysConstService.updateAccessTokenByWXXcx();
	// } else if (code.equals(0)) {
	// // 发送成功，做相应的逻辑处理
	// boxIdList.add(boxId);
	// }
	// }
	// });
	// }
	// if (!boxIdList.isEmpty()) {// 发送消息成功的
	// Date date = new Date();
	// // 1.批量修改发送消息后的储物柜信息
	// ManageCaseBox manageCaseBoxRecord = new ManageCaseBox();
	// manageCaseBoxRecord.setSendXcxMessageFlag((byte) 1);
	// manageCaseBoxRecord.setSendClearMessageTime(date);
	// ManageCaseBoxExample updatemanageCaseBoxExample = new ManageCaseBoxExample();
	// updatemanageCaseBoxExample.createCriteria().andIdIn(boxIdList);
	// manageCaseBoxMapper.updateByExampleSelective(manageCaseBoxRecord,
	// updatemanageCaseBoxExample);
	//
	// }
	//
	// }
	//
	// }

	/**
	 * @author liuCheng
	 * @since 2018年12月27日 下午3:51:39 更新token
	 */
	public void updateAccessTokenByWXXcx() {
		sysConstService.updateAccessTokenByWXXcx();

	}

	/**
	 * @author liuCheng
	 * @since 2018年12月27日 下午4:31:29 定时清除超时储物柜
	 */
	public void clearBox() {
		Date date = new Date();
		String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");
		List<CustomersAmount> customersAmountList = new ArrayList<>();
		List<AccessRecord> insertBatchList = new ArrayList<>();
		// 查询出需要清理的记录

		ManageCaseBoxExample caseBoxExample = new ManageCaseBoxExample();
		caseBoxExample.createCriteria().andUseStatusEqualTo((byte) 1).andIsDelEqualTo((byte) 0)
				.andClearBoxTimeLessThanOrEqualTo(date);
		List<ManageCaseBox> manageCaseBoxList = manageCaseBoxMapper.selectByExample(caseBoxExample);

		if (!manageCaseBoxList.isEmpty()) {// 不为空，进行清除操作
			List<Integer> boxIdList = manageCaseBoxList.stream()
					.collect(Collectors.mapping(ManageCaseBox::getId, Collectors.toList()));

			List<String> caseNoList = manageCaseBoxList.stream()
					.collect(Collectors.mapping(ManageCaseBox::getCaseNo, Collectors.toList())).stream().distinct()
					.collect(Collectors.toList());
			ManageCaseExample manageCaseExample = new ManageCaseExample();
			manageCaseExample.createCriteria().andCaseNoIn(caseNoList);
			List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(manageCaseExample);
			Map<String, ManageCase> caseNoMap = manageCaseList.stream()
					.collect(Collectors.toMap(ManageCase::getCaseNo, v -> v));

			List<Integer> typeIdList = manageCaseList.stream()
					.collect(Collectors.mapping(ManageCase::getTypeId, Collectors.toList())).stream().distinct()
					.collect(Collectors.toList());

			ManageCaseTypeExample CaseTypeExample = new ManageCaseTypeExample();
			CaseTypeExample.createCriteria().andTypeIdIn(typeIdList);
			List<ManageCaseType> manageCaseTypeList = manageCaseTypeMapper.selectByExample(CaseTypeExample);
			Map<Integer, ManageCaseType> typeIdMap = manageCaseTypeList.stream()
					.collect(Collectors.toMap(ManageCaseType::getTypeId, v -> v));

			// 1.修改储物柜状态
			ManageCaseBox manageCaseBoxRecord = new ManageCaseBox();
			manageCaseBoxRecord.setUseStatus((byte) 0);
			ManageCaseBoxExample updatemanageCaseBoxExample = new ManageCaseBoxExample();
			updatemanageCaseBoxExample.createCriteria().andIdIn(boxIdList);
			manageCaseBoxMapper.updateByExampleSelective(manageCaseBoxRecord, updatemanageCaseBoxExample);

			manageCaseBoxList.stream().forEach(a -> {
				String caseNo = a.getCaseNo();
				ManageCase manageCase = caseNoMap.get(caseNo);
				Integer typeId = manageCase.getTypeId();
				ManageCaseType manageCaseType = typeIdMap.get(typeId);
				double amount = CustomersAmountCount.getAliCharge(a, manageCase, manageCaseType);
				Date saveTime = a.getSaveTime();
				String userId = a.getUserId();

				Byte saveSource = a.getSaveSource();
				AccessRecord accessRecord = SavaSourceToRecordSource.savaSourceToRecordSource(saveSource);
				accessRecord.setBoxId(a.getId());
				accessRecord.setCharge(BigDecimal.valueOf(-amount));
				accessRecord.setCreateTime(date);
				accessRecord.setCreateDay(dateStr);
				accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.TIME_OUT_BYONESELF);
				accessRecord.setUserId(userId);
				accessRecord.setUseTime(date.getTime() - saveTime.getTime());
				// 金额
				if (amount > 0) {
					CustomersAmount customersAmount = new CustomersAmount();
					customersAmount.setOpenId(userId);
					customersAmount.setTotalAmount(BigDecimal.valueOf(amount));
					customersAmountList.add(customersAmount);
				}

				insertBatchList.add(accessRecord);
			});

			// 2.插入清除记录
			accessRecordMapper.insertBatch(insertBatchList);
			// 3.修改用户的账户余额
			if (!customersAmountList.isEmpty()) {
				customersAmountMapper.updateUserAmount(customersAmountList);
			}

		}

	}
}